package com.niuma.dao;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @author 一颗蛋50斤
 * 操作数据库公共类
 */
public class BaseDao {
    private static String driver;
    private static String url;
    private static String userName;
    private static String password;

    // 静态代码块，加载类的时候初始化
    static {
        Properties properties = new Properties();
        // 通过类加载器读取对应的资源
        InputStream inputStream = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");

        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        userName = properties.getProperty("username");
        password = properties.getProperty("password");
    }

    /**
     * 创建一个数据库连接对象
     * @return 数据库连接对象
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, userName, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 查询公共方法
     * @param connection 数据库连接对象
     * @param preparedStatement 数据库操作对象
     * @param resultSet 结果集合
     * @param sql SQL 语句
     * @param params 参数列表
     * @return 查询到的结果
     * @throws SQLException 数据库操作异常
     */
    public static ResultSet execute(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet,
                                    String sql, Object[] params) throws SQLException {
        // 预编译
        preparedStatement = connection.prepareStatement(sql);

        // 将数据列表中的元素遍历插入预编译中
        for (int i = 0; i < params.length; i++) {
            // 因为不知道将来数据列表中的元素是什么数据类型的，所以将其设置为 Object 类型
            preparedStatement.setObject(i + 1, params[i]);
        }

        // 因为我们这边只是做查询，所以我们就选择执行查询操作的方法，这样会比较快
        resultSet = preparedStatement.executeQuery();
        return resultSet;
    }

    /**
     * 增 删 改 公共方法
     * @param connection 数据库连接对象
     * @param preparedStatement 数据库操作对象
     * @param sql SQL 语句
     * @param params 元素列表
     * @return 受影响的行数
     * @throws SQLException 数据库操作异常
     */
    public static int execute(Connection connection, PreparedStatement preparedStatement, String sql, Object[] params)
            throws SQLException {
        // 预编译
        preparedStatement = connection.prepareStatement(sql);

        for (int i = 0; i < params.length; i++) {
            preparedStatement.setObject(i+1, params[i]);
        }

        int resultRows = preparedStatement.executeUpdate();
        return resultRows;
    }

    /**
     * 释放资源
     * @param connection 数据库连接对象
     * @param preparedStatement 数据库操作对象
     * @param resultSet 查询结果集
     * @return true or false
     */
    public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet)
    {
        boolean flag = true;

        if (resultSet != null) {
            try {
                resultSet.close();
                // GC 回收
                resultSet = null;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                flag = false;
            }
        }

        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                preparedStatement = null;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                flag = false;
            }
        }

        if (connection != null) {
            try {
                connection.close();
                connection = null;
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                flag = false;
            }
        }

        return flag;
    }
}
